package org.wheel.plugins.toolkit.sql.capability;

import org.wheel.plugins.toolkit.sql.core.AbstractWrapper;
import org.wheel.plugins.toolkit.sql.enums.CompareType;
import org.wheel.plugins.toolkit.sql.helper.SFunction;
import org.wheel.plugins.toolkit.sql.segment.JoinType;
import org.wheel.plugins.toolkit.sql.segment.OnClause;

import java.util.function.Consumer;

/**
 * 统一 Lambda 风格 Join 能力
 * @param <T> 主实体
 * @param <W> 具体 Wrapper 类型，用于链式返回自身
 */
public interface LambdaJoin<W extends LambdaJoin<W, T>, T> {

    /* ========== 默认 Join 语法糖 ========== */
    default <J> W leftJoin(Class<J> joinClazz, Consumer<OnClause<J>> on) {
        return join(JoinType.LEFT, joinClazz, null, on);
    }

    default <J, D> W leftJoin(Class<J> joinClazz, String tableAlias, SFunction<J, ?> leftCol, SFunction<D, ?> rightCol) {
        return join(JoinType.LEFT, joinClazz, tableAlias, leftCol, null, rightCol);
    }
    default <J, D> W leftJoin(Class<J> joinClazz, SFunction<J, ?> leftCol, SFunction<D, ?> rightCol) {
        return join(JoinType.LEFT, joinClazz, null, leftCol, null, rightCol);
    }

    default <J> W leftJoin(Class<J> joinClazz, String tableAlias, Consumer<OnClause<J>> on) {
        return join(JoinType.LEFT, joinClazz, tableAlias, on);
    }

    default <J> W rightJoin(Class<J> joinClazz, Consumer<OnClause<J>> on) {
        return join(JoinType.RIGHT, joinClazz, null, on);
    }

    default <J, D> W rightJoin(Class<J> joinClazz, String tableAlias, SFunction<J, ?> leftCol, SFunction<D, ?> rightCol) {
        return join(JoinType.RIGHT, joinClazz, tableAlias, leftCol, null, rightCol);
    }
    default <J, D> W rightJoin(Class<J> joinClazz, SFunction<J, ?> leftCol, SFunction<D, ?> rightCol) {
        return join(JoinType.RIGHT, joinClazz, null, leftCol, null, rightCol);
    }

    default <J> W rightJoin(Class<J> joinClazz, String tableAlias, Consumer<OnClause<J>> on) {
        return join(JoinType.RIGHT, joinClazz, tableAlias, on);
    }

    default <J> W innerJoin(Class<J> joinClazz, Consumer<OnClause<J>> on) {
        return join(JoinType.INNER, joinClazz, null, on);
    }

    default <J, D> W innerJoin(Class<J> joinClazz, SFunction<J, ?> leftCol, SFunction<D, ?> rightCol) {
        return join(JoinType.INNER, joinClazz, null, leftCol, null, rightCol);
    }

    default <J, D> W innerJoin(Class<J> joinClazz, String tableAlias, SFunction<J, ?> leftCol, SFunction<D, ?> rightCol) {
        return join(JoinType.INNER, joinClazz, tableAlias, leftCol, null, rightCol);
    }

    default <J> W innerJoin(Class<J> joinClazz, String tableAlias, Consumer<OnClause<J>> on) {
        return join(JoinType.INNER, joinClazz, tableAlias, on);
    }

    default <J1, J> W join(JoinType joinType, Class<J> joinClazz,  String leftTableAlias, SFunction<J, ?> leftCol,  String rightTableAlias, SFunction<J1, ?> rightCol) {
        return join(joinType, joinClazz, null, on->on.compareCol(CompareType.EQ, leftTableAlias, leftCol, rightTableAlias, rightCol));
    }

    /* ========== 唯一需要实现的方法 ========== */
    <J> W join(JoinType joinType, Class<J> joinClazz, String tableAlias, Consumer<OnClause<J>> on);


}